package com.jwsoft.manager.core.dao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.module.base.common.util.CommonSecureUtil;
import com.jwsoft.manager.common.enums.EduStatusTypeEnum;
import com.jwsoft.manager.common.vo.bigScreen.analysisXq.StuEnrollInVO;
import com.jwsoft.manager.common.vo.bigScreen.analysisXq.StuEnrollXzjdpmVO;
import com.jwsoft.manager.common.vo.dataStatistics.enroll.*;
import com.jwsoft.manager.common.vo.eduDataTaskDetail.DataTaskDetailOptionVO;
import com.jwsoft.manager.common.vo.eduStudentEnroll.EduStudentEnrollQueryVO;
import com.jwsoft.manager.common.vo.eduStudentEnroll.EduStudentEnrollVO;
import com.jwsoft.manager.core.dao.mapper.*;
import com.jwsoft.manager.core.dao.model.*;
import com.jwsoft.manager.core.dao.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.springframework.beans.BeanUtils.copyProperties;

/**
 * 服务实现类
 *
 * @author wangtao
 * @since 2022-12-05
 */
@Service
@Slf4j
public class DyEduStudentEnrollServiceImpl extends ServiceImpl<DyEduStudentEnrollMapper, EduStudentEnroll> implements DyEduStudentEnrollService, TableService {
    @Autowired
    private EduDataTaskDetailService detailService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private EdutStudentEnrollMapper tStudentEnrollMapper;

    @Autowired
    private EduhStudentEnrollMapper hStudentEnrollMapper;

    @Autowired
    private EduAddressSchoolDifferentStreetService
            addressSchoolDifferentStreetService;

    @Autowired
    private EduAddressSchoolDifferentStreetMapper differentStreetMapper;


    //每次处理的数量为1w条数据
    private static final Integer PAGE_SIZE = 10000;
    @Override
    public List<EduStudentEnrollVO> getYwApplyList(EduStudentEnrollQueryVO vo) {
        if ("1".equalsIgnoreCase(vo.getIsbqFlag())) {
            vo.setBbFlag(BoolEnum.TRUE.getType());
        } else if ("2".equalsIgnoreCase(vo.getIsbqFlag())) {
            vo.setSpareRegisterFlag(BoolEnum.TRUE.getType());
        }
        return baseMapper.getYwApplyList(vo);
    }

    @Override
    public List<EduStudentEnrollVO> getYwApplyListYq(EduStudentEnrollQueryVO vo) {
        if ("1".equalsIgnoreCase(vo.getIsbqFlag())) {
            vo.setBbFlag(BoolEnum.TRUE.getType());
        } else if ("2".equalsIgnoreCase(vo.getIsbqFlag())) {
            vo.setSpareRegisterFlag(BoolEnum.TRUE.getType());
        }
        return baseMapper.getYwApplyListYq(vo);

    }

    @Override
    public List<StuEnrollXzjdpmVO> getStuEnrollXzjdpmVO(StuEnrollInVO vo) {
        return baseMapper.getStuEnrollXzjdpmVO(vo);
    }

    @Override
    public String queryMaxApplyId(String applyId, String schoolId, Integer year) {
        return baseMapper.queryMaxApplyId(applyId, schoolId, year);
    }

    @Override
    public List<EduStudentEnrollVO> getEnrollLotteryList(EduStudentEnrollQueryVO vo) {
        return baseMapper.getEnrollLotteryList(vo);
    }

    @Override
    public List<NoEnrollStudentVO> queryNoEnrollStudent(EnrollStudentQueryVO vo) {
        return baseMapper.queryNoEnrollStudent(vo);
    }

    @Override
    public List<EduStudentEnroll> queryEnrollStudentNotInClassStudent(Integer year, String schoolId, Integer queryMaxSize, String enrollStatus) {
        return baseMapper.queryEnrollStudentNotInClassStudent(year, schoolId, queryMaxSize, enrollStatus);
    }

    @Override
    public Long getBackCnt(Integer year, String idcard) {
        return baseMapper.getBackCnt(year, idcard);
    }

    @Override
    public List<EnrollStatisticsVO> enrollStatistics(EnrollStudentQueryVO vo) {
        //公办学校有足球特招生之类的，所以不关联config_type_name
             vo.setSchoolNatureList(Arrays.asList("0"));
            List<EnrollStatisticsVO> listGb = baseMapper.enrollStatistics(vo);

            vo.setSchoolNatureList(Arrays.asList("1","2"));
            List<EnrollStatisticsVO> listMbOrMzg =  baseMapper.enrollStatisticsMb(vo);

            List<EnrollStatisticsVO> combinedList = Stream.concat(listMbOrMzg.stream(), listGb.stream())
                .collect(Collectors.toList());
            return combinedList;
    }

    @Override
    public List<EnrollStatisticsVO> getauthNoList(EnrollStudentQueryVO vo) {
        return baseMapper.getauthNoList(vo);
    }

    @Override
    public List<EnrollStatisticsVO> enrollStatisticsImitate(EnrollStudentQueryVO vo) {
        return baseMapper.enrollStatisticsImitate(vo);
    }

    @Override
    public List<EnrollStatisticsVO> getauthNoListImitate(EnrollStudentQueryVO vo) {
        return baseMapper.getauthNoListImitate(vo);
    }

    /**
     * @param optionVO
     * @return
     */
    @Override
    public Integer dataMigration(DataTaskDetailOptionVO optionVO) {
        EduDataTaskDetail taskDetail = detailService.getById(optionVO.getTaskDetailId());
        log.info("调用了EduStudentEnrollServiceImpl服务的dataMigration()来进行处理迁移数据");
        Integer count = this.baseMapper.selectCountByYear(optionVO.getYear());
        log.info("edu_student_enroll迁移" + count + "条数据");
        // 计算总页数
        int totalPages = (count % PAGE_SIZE == 0) ? (count / PAGE_SIZE) : (count / PAGE_SIZE + 1);
        // 计算循环次数 = 总页数
        for (int i = 0; i < totalPages; i++) {
            List<EduStudentEnroll> studentEnrolls = this.baseMapper.selectByYear(optionVO.getYear());
            if (studentEnrolls.size() > 0) {
                List<EduhStudentEnroll> hStudentEnrolls = studentEnrolls.stream().map(item -> {
                    EduhStudentEnroll eduhStudentEnroll = new EduhStudentEnroll();
                    BeanUtils.copyProperties(item, eduhStudentEnroll);
                    eduhStudentEnroll.setTaskDetailId(taskDetail.getTaskDetailId());
                    //数据是否已加密，初始状态未加密
                    eduhStudentEnroll.setEncryptFlag(BoolEnum.FALSE.getType());
                    eduhStudentEnroll.setEncryptStatus(EduStatusTypeEnum.dcl.getType());
                    eduhStudentEnroll.setCleanFlag(BoolEnum.FALSE.getType());
                    return eduhStudentEnroll;
                }).collect(Collectors.toList());
                try {
                    this.performDataMigration(hStudentEnrolls, studentEnrolls.size(),optionVO);
                } catch (Exception e) {
                    log.error("edu_student_enroll迁移数据发生异常");
                    throw new RuntimeException("EduStudentEnrollServiceImpl:" + e);
                }
            }
        }
        return count;
    }

    private void performDataMigration(List<EduhStudentEnroll> hStudentEnrolls, Integer count, DataTaskDetailOptionVO optionVO) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    //1.数据迁移到历史表
                    int saveHCount = hStudentEnrollMapper.saveBatch(hStudentEnrolls);
                    if (saveHCount != count) {
                        throw new RuntimeException("数据迁移到历史表失败");
                    }
                    //2.数据销毁
                    EduDataTaskDetail taskDetail = detailService.getById(optionVO.getTaskDetailId());
                    if (ObjectUtils.isEmpty(taskDetail)) {
                        throw new AppException("任务数据不存在，请检查数据是否有误");
                    }
                    Integer deleteCount = baseMapper.deleteByTaskHistory(taskDetail.getTaskDetailId());
                    if (!count.equals(deleteCount)) {
                        throw new RuntimeException("数据删除失败");
                    }
                    log.info("edu_student_enroll数据销毁成功！销毁数量：" + count);
                } catch (Exception e) {
                    status.setRollbackOnly();
                    throw e;
                }
            }
        });
    }

    @Override
    public void dataEncryption(DataTaskDetailOptionVO optionVO) {
        EduDataTaskDetail taskDetail = detailService.getById(optionVO.getTaskDetailId());
        log.info("调用了EduStudentEnrollServiceImpl服务的dataEncryption()来进行处理数据加密");
        Integer count = 0;
        if (taskDetail.getEncryptCount() == 0) {
            count = this.baseMapper.selectEncryptionCountByYear(optionVO.getYear(), optionVO.getTaskDetailId());
            taskDetail.setEncryptCount(count);
        }
        Boolean errorFlag = false;
        Integer errorCount = 0;
        int totalPages = (count % PAGE_SIZE == 0) ? (count / PAGE_SIZE) : (count / PAGE_SIZE + 1);
        // 计算循环次数 = 总页数
        for (int i = 0; i < totalPages; i++) {
            List<EduhStudentEnroll> hStudentEnrolls =
                    this.baseMapper.selectEncryptionByYear(optionVO.getYear(), optionVO.getTaskDetailId(), PAGE_SIZE);
            for (EduhStudentEnroll hStudentEnroll : hStudentEnrolls) {
                //加密
                try {
                    this.encrypt(hStudentEnroll);
                    hStudentEnroll.setEncryptTime(new Date());
                    hStudentEnroll.setEncryptStatus(EduStatusTypeEnum.success.getType());
                    hStudentEnroll.setEncryptRemarks("加密成功");
                    hStudentEnroll.setEncryptFlag(BoolEnum.TRUE.getType());
                    hStudentEnrollMapper.updateById(hStudentEnroll);
                } catch (Exception e) {
                    //解密
                    this.decrypt(hStudentEnroll);
                    hStudentEnroll.setEncryptTime(new Date());
                    hStudentEnroll.setEncryptStatus(EduStatusTypeEnum.error.getType());
                    hStudentEnroll.setEncryptFlag(BoolEnum.FALSE.getType());
                    hStudentEnroll.setEncryptRemarks("加密失败"+e.getMessage());
                    hStudentEnrollMapper.updateById(hStudentEnroll);
                    errorFlag = true;
                    errorCount++;
                    throw new AppException(e);
                }
            }
        }
        if (!errorFlag) {
            //无异常，返回任务状态
            taskDetail.setEncryptStatus(EduStatusTypeEnum.success.getType());
            taskDetail.setEncryptRemarks("加密成功");
            taskDetail.setEncryptTime(new Date());
        } else {
            taskDetail.setEncryptStatus(EduStatusTypeEnum.error.getType());
            taskDetail.setEncryptTime(new Date());
            taskDetail.setEncryptRemarks(taskDetail.getHandleTable()
                    +"加密失败,加密出错的数据：" + errorCount);
        }
        detailService.updateById(taskDetail);
    }

    private void decrypt(EduhStudentEnroll hStudentEnroll) {
        if (StringUtils.isNotBlank(hStudentEnroll.getFullName())){
            hStudentEnroll.setFullName(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getFullName()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getIdcard())){
            hStudentEnroll.setIdcard(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getIdcard()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getCellphone())){
            hStudentEnroll.setCellphone(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getCellphone()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getAddress())){
            hStudentEnroll.setAddress(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getAddress()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getFatherName())){
            hStudentEnroll.setFatherName(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getFatherName()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getFatherIdcard())){
            hStudentEnroll.setFatherIdcard(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getFatherIdcard()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getFatherCellphone())){
            hStudentEnroll.setFatherCellphone(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getFatherCellphone()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getMotherName())){
            hStudentEnroll.setMotherName(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getMotherName()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getMotherIdcard())){
            hStudentEnroll.setMotherIdcard(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getMotherIdcard()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getMotherCellphone())){
            hStudentEnroll.setMotherCellphone(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getMotherCellphone()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getHouseholdAddress())){
            hStudentEnroll.setHouseholdAddress(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getHouseholdAddress()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getHouseAdreess())){
            hStudentEnroll.setHouseAdreess(CommonSecureUtil.sm4Decrypt(hStudentEnroll.getHouseAdreess()));
        }
    }

    private void encrypt(EduhStudentEnroll hStudentEnroll) {
        if (StringUtils.isNotBlank(hStudentEnroll.getFullName())){
            hStudentEnroll.setFullName(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getFullName()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getIdcard())){
            hStudentEnroll.setIdcard(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getIdcard()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getCellphone())){
            hStudentEnroll.setCellphone(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getCellphone()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getAddress())){
            hStudentEnroll.setAddress(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getAddress()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getFatherName())){
            hStudentEnroll.setFatherName(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getFatherName()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getFatherIdcard())){
            hStudentEnroll.setFatherIdcard(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getFatherIdcard()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getFatherCellphone())){
            hStudentEnroll.setFatherCellphone(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getFatherCellphone()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getMotherName())){
            hStudentEnroll.setMotherName(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getMotherName()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getMotherIdcard())){
            hStudentEnroll.setMotherIdcard(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getMotherIdcard()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getMotherCellphone())){
            hStudentEnroll.setMotherCellphone(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getMotherCellphone()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getHouseholdAddress())){
            hStudentEnroll.setHouseholdAddress(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getHouseholdAddress()));
        }
        if (StringUtils.isNotBlank(hStudentEnroll.getHouseAdreess())){
            hStudentEnroll.setHouseAdreess(CommonSecureUtil.sm4Encrypt(hStudentEnroll.getHouseAdreess()));
        }
    }

    @Override
    public Integer dataDestruction(DataTaskDetailOptionVO optionVO) {
      //学生报名数据不做销毁处理
      return 0;
    }

    @Override
    public void tempDataDestruction() {

    }

    @Override
    public void dataDecrypt(DataTaskDetailOptionVO optionVO) {
        Integer count = Math.toIntExact(hStudentEnrollMapper.selectCount(new QueryWrapper<EduhStudentEnroll>().lambda().eq(EduhStudentEnroll::getTaskDetailId, optionVO.getTaskDetailId())));
        int totalPages = (count % PAGE_SIZE == 0) ? (count / PAGE_SIZE) : (count / PAGE_SIZE + 1);
        int currentPage = 0;
        // 计算循环次数 = 总页数
        for (int i = 0; i < totalPages; i++) {
            List<EduhStudentEnroll> hStudentEnrolls =
                    hStudentEnrollMapper.selectByTaskDetailId(optionVO.getTaskDetailId(),currentPage,PAGE_SIZE);
            List<EdutStudentEnroll> tStudentEnrollList = hStudentEnrolls.stream().map(eduhStudentEnroll -> {
                if (BoolEnum.TRUE.getType().equalsIgnoreCase(eduhStudentEnroll.getEncryptFlag())) {
                    //需要进行解密
                    this.decrypt(eduhStudentEnroll);
                }
                EdutStudentEnroll edutStudentEnroll = new EdutStudentEnroll();
                BeanUtils.copyProperties(eduhStudentEnroll, edutStudentEnroll);
                return edutStudentEnroll;
            }).collect(Collectors.toList());
            tStudentEnrollMapper.saveBatch(tStudentEnrollList);
            currentPage++;
        }
    }

    @Override
    public List<NoAssociatedAddressVO> noAssociatedAddress(EnrollStudentQueryVO vo) {
        return baseMapper.noAssociatedAddress(vo);
    }

    @Override
    public List<SameAddressSchoolVO> sameAddressSchool(EnrollStudentQueryVO vo) {
        return baseMapper.sameAddressSchool(vo);
    }

    @Override
    public List<SameAddressSchoolDetailVO> sameAddressSchoolDetail(EnrollStudentQueryVO vo) {
        return baseMapper.sameAddressSchoolDetail(vo);
    }

    @Override
    public List<SameAddressSchoolDetailVO> sameAddressSchoolDetailSchool(EnrollStudentQueryVO vo) {
        return baseMapper.sameAddressSchoolDetailSchool(vo);
    }

    @Override
    public List<ServerRelationNoSchoolRelataionVO> serverRelationButNoAssociatedAddress(EnrollStudentQueryVO vo) {
        return baseMapper.serverRelationButNoAssociatedAddress(vo);
    }

    @Override
    public List<EnrollStatisticsVO> allKindStatistic(EnrollStudentQueryVO vo) {
        return baseMapper.allKindStatistic(vo);
    }

    @Override
    public List<AuthNoAllKindVO> getauthNoAllKindList(EnrollStudentQueryVO vo) {
        return baseMapper.getauthNoAllKindList(vo);
    }

    @Override
    public List<SameAddressSchoolDetailVO> sameAddressSchoolStreet(EnrollStudentQueryVO vo) {
        return baseMapper.sameAddressSchoolStreet(vo);
    }

    @Override
    public List<SameAddressSchoolDetailVO> sameAddressSchoolStreetSchool(EnrollStudentQueryVO vo) {
        return baseMapper.sameAddressSchoolStreetSchool(vo);
    }

    @Override
    public List<SameAddressSchoolDetailVO> getEduAddressSchoolDifferentStreet(EnrollStudentQueryVO vo) {
        return baseMapper.getEduAddressSchoolDifferentStreet(vo);
    }
}
